﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net.Sockets;
using System.Net;

using cc2530.Lib.contiki;

using System.Threading;
using System.Windows.Forms;


using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;


namespace cc2530
{
    //基于 contikNode的泛型类
    public class udpArg<Tnode>where Tnode :contikiNode,new()
    {
        public UdpClient uc;
        public IPEndPoint endp;
        public Tnode node;
        public AutoResetEvent are;
        public Control parent;

        public udpArg() { }
    }

   public class contikiNodeArgs:EventArgs{
       public contikiNode node;
       public DateTime StartTime;
       public DateTime EndTime;
    }

   public class contikiNeighborArgs : EventArgs {
       public contikiNode node;    //节点
       public contikiNode neighbor;//节点的neighbor
   }
    public delegate void onContikiNodeGet(object sender,contikiNodeArgs args);
    public delegate void onContikiNeighborGet(object sender,contikiNeighborArgs args);

    public class TreeRead<Tnode> where Tnode :contikiNode,new()
    {

        #region 读取字点数据
        Tnode root;
        Control _parent;
        Thread thread;
        int timeout = 4000;//4 seconds
        DateTime StartTime;
        public TreeRead(Control parent) { _parent = parent; }
        public TreeRead(Tnode node, int port, Control parent)
            : this(parent)
        { }

        /// <summary>
        /// 所有节点
        /// </summary>
        public List<Tnode> ListOfNodes { get { return this.lnodes; } }


        /// <summary>
        /// 取得所有节点
        /// </summary>
        /// <param name="_root"></param>
        public void GetAllNodes(Tnode _root)
        {
            root = _root;
            //ListOfNodes.Add(_root);
            //_root.BelongTo = ListOfNodes as List<contikiNode>;
            ThreadStart start = new ThreadStart(Run);
            this.thread = new Thread(start);
            thread.Start();
            StartTime = System.DateTime.Now;
        }
        public void Stop() {
            if (this.thread != null) {
                this.thread.Abort();
            }
        }

        /// <summary>
        /// 运行状态
        /// </summary>
        public bool IsRunning
        {
            get
            {
                if (thread != null)
                {
                    if (thread.ThreadState == ThreadState.Running) return true;
                }

                return false;
            }
        }

       /// 事件
        public event onContikiNodeGet oncontikiNodeGet;
        public event onContikiNeighborGet oncontikiNeighborGet;
        public event onContikiNodeGet oncontikiNodeGetFinished;

        /// <summary>
        /// 内部线程
        /// </summary>
        private void Run()
        {
            root = _GetAllNode(root);

            //获取完成
            if (oncontikiNodeGetFinished != null) {
                contikiNodeArgs args = new contikiNodeArgs();
                args.node = root;
                args.StartTime = StartTime;
                args.EndTime = System.DateTime.Now;
                oncontikiNodeGetFinished(this, args);
            }
        }



        /// <summary>
        /// 用于所有节点
        /// </summary>
        List<Tnode> lnodes = new List<Tnode>();

        public void NodesClear() { lnodes.Clear(); }

        bool IsValid(Tnode node)
        {
            foreach (Tnode _n in lnodes)
            {
                if (_n.name == node.name) return true;
            }
            return false;
        }


        Tnode IsValid(string name) {
            foreach (Tnode _n in lnodes)
            {
                if (_n.name == name) return _n;
            }
            return null;          
        }

        private Tnode _GetAllNode(Tnode _root)
        {
            if (IsValid(_root) == false)
            {
                //节点没有存在
                lnodes.Add(_root);
                if (this.oncontikiNodeGet != null)
                {
                    contikiNodeArgs args = new contikiNodeArgs();
                    args.node = _root;
                    oncontikiNodeGet(this, args);
                }

                //pc节点不用get
                if (_root.ntype != NodeType.PCnode)
                {
                    _root = GetOneNode(_root).node;
                    _root.BelongTo = lnodes as List<contikiNode>;
                    foreach (Tnode c in _root.Neighbors)
                    {
                        if (IsValid(c) == false) _GetAllNode(c);
                    }
                }
            }

            return _root;
        }

        /// <summary>
        /// 读得当前节点的 下一级节点
        /// </summary>
        /// <param name="one"></param>
        /// <returns></returns>
        public udpArg<Tnode> GetOneNode(Tnode one)
        {
            udpArg<Tnode> arg = new udpArg<Tnode>();
            arg.uc = new UdpClient(AddressFamily.InterNetworkV6);
            arg.node = one;
            arg.endp = new IPEndPoint(one.IP, 60001);
            arg.parent = _parent;
            arg.are = new AutoResetEvent(false);
            arg.uc.Connect(arg.endp);
            {
                byte[] request = new byte[1] { 1 };
                arg.uc.Send(request, request.Length);
            }
            IAsyncResult ar = arg.uc.BeginReceive(EndReceive, arg);
            arg.are.WaitOne(timeout, false);
            arg.uc.Close();
            return arg;
        }


        public int NodeTimeOut { get { return timeout; } set { timeout = value; } }

        /// <summary>
        /// 内部异步线程，用来处理接收到的数据 
        /// </summary>
        /// <param name="ar"></param>
        private void EndReceive(IAsyncResult ar)
        {
            udpArg<Tnode> s = ar.AsyncState as udpArg<Tnode>;
            try
            {
                if (s != null)
                {   //     0         1    26*n+2      26*n+3        26*n+19     26*n + 27
                    //  request -- count---[i(1)-------ip(16)-------mac(8)-------state(1)]
                    Byte[] receiveBytes = s.uc.EndReceive(ar, ref s.endp);
                    if (receiveBytes != null && receiveBytes[1] != 0)
                    {

                        System.Console.WriteLine(BitConverter.ToString(receiveBytes).Replace("-", " "));
                        //有邻居  
                        int count = receiveBytes[1];
                        for (int i = 0; i < count; i++)
                        {
                            Tnode n = new Tnode();
                            try
                            {
                                n.IP = IPAddress.Parse(IPv6Address.AddressToString(receiveBytes, 3 + i * 26));
                                n.IP = IPv6Address.IPv6IPAddressWithPrefix("aaaa::", 64, n.IP);                                
                                Array.Copy(receiveBytes, 3 + 16 + i * 26, n.Mac, 0, 8);
                                n.state = (contikiNodeState)receiveBytes[3 + 16 + 8 + i * 26];
                            }
                            catch
                            {
                                continue;
                            }
                            ///必须使用invoke 前台进程
                            s.parent.Invoke((Action)delegate
                            {
                                //---------------//转换mac :FFFE 的是pc  其它的是 contiki nodes or routers
                                if (n.Mac[3] == 0xFF && n.Mac[4] == 0xFE) n.ntype = NodeType.PCnode;                                
                                if (oncontikiNeighborGet != null) {
                                    contikiNeighborArgs narg = new contikiNeighborArgs();
                                    narg.node = s.node;
                                    narg.neighbor = n;
                                    oncontikiNeighborGet(this, narg);
                                }

                                contikiNode bn = IsValid(n.name);

                                //节点是否已经存在，已经存在，加原来的节点作为邻居，不存在，加新的节点作为邻居
                                if (bn != null) s.node.Neighbors.Add(n);
                                else
                                {
                                    s.node.Neighbors.Add(n);
                                }


                            });
                        }
                    }
                }
                //没有邻居 
                //return s;
            }
            catch (Exception ex)
            {
                //处理异常  
                System.Console.WriteLine("GetOneNode EndReceive Error:" + ex.ToString());
            }
            s.are.Set();
        }


        #endregion
    }



}
